Skip to content

Add overridable cache type - #13250

Merged
jerelmiller merged 34 commits into
release-4.3from
jerel/cache-type
Jun 9, 2026
Merged

Add overridable cache type#13250
jerelmiller merged 34 commits into
release-4.3from
jerel/cache-type

Conversation

@jerelmiller

@jerelmiller jerelmiller commented Jun 2, 2026

Copy link
Copy Markdown
Member

Currently client.cache always return an ApolloCache type, regardless of the actual cache instance you provide to ApolloClient. This can be slightly annoying in cases where you might want to access cache through client.cache and work directly with e.g. InMemoryCache specific APIs. Currently this requires a type override, or access to the original cache instance from elsewhere in your app.

This PR adds the ability to specify the cache implementation in the TypeOverrides interface using the cache property. Anywhere cache is accessible, its type will be the override type (e.g. client.cache // => InMemoryCache). To ensure the runtime value matches the declared type, ApolloClient.Options has been updated to enforce the implemented type.

// apollo.d.ts
import type { InMemoryCache } from "@apollo/client";

declare module "@apollo/client" {
  export interface TypeOverrides {
    cache: InMemoryCache;
  }
}

Summary by CodeRabbit

  • New Features

    • Client cache typing can be customized via TypeScript augmentation and now propagates to client.cache, mutation/refetch callbacks, and React hooks for stronger, consistent type safety.
  • Tests

    • Added comprehensive type tests covering classic/modern signatures and hook scenarios to validate cache-override behavior.
  • Documentation

    • Added guidance and examples showing how to declare a custom cache type and how it affects client APIs.

@jerelmiller
jerelmiller requested a review from phryneas June 2, 2026 05:27
@apollo-librarian

apollo-librarian Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

✅ Docs preview ready

The preview is ready to be viewed. View the preview

File Changes

0 new, 3 changed, 0 removed
* (developer-tools)/react/(latest)/data/fragments.mdx
* (developer-tools)/react/(latest)/data/typescript.mdx
* (developer-tools)/react/(latest)/migrating/apollo-client-4-migration.mdx

Build ID: 8f5e944383c23361471a8603
Build Logs: View logs

URL: https://www.apollographql.com/docs/deploy-preview/8f5e944383c23361471a8603


✅ AI Style Review — No Changes Detected

No MDX files were changed in this pull request.

Review Log: View detailed log

This review is AI-generated. Please use common sense when accepting these suggestions, as they may not always be accurate or appropriate for your specific context.

@changeset-bot

changeset-bot Bot commented Jun 2, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 8df9c40

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@apollo/client Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: c13adae7-2261-44b8-be6f-c7033841373b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR adds a conditional type, Cache.Implementation (derived from TypeOverrides.cache or falling back to ApolloCache), updates ApolloClient core types and useMutation/react hook typings to use that type, updates deprecated aliases and API reports, and adds comprehensive integration type tests and TS project wiring.

Changes

Cache Type Override Implementation

Layer / File(s) Summary
Cache.Implementation type definition
src/cache/core/types/Cache.ts, .api-reports/api-report-cache.api.md
A new Cache.Implementation conditional type is introduced that resolves to TypeOverrides.cache when declared, otherwise defaults to ApolloCache.
ApolloClient core typing
src/core/ApolloClient.ts, .api-reports/api-report-core.api.md, .api-reports/api-report.api.md
ApolloClient.Options.cache, ApolloClient.cache, mutate, refetchQueries, and related mutation helpers now use Cache.Implementation instead of ApolloCache for cache generic constraints and defaults.
useMutation hook typing
src/react/hooks/useMutation.ts, .api-reports/api-report-react.api.md
useMutation's Options, MutationFunction, ResultTuple, MutationFunctionOptions, ResultForOptions, and signature overloads all update to use Cache.Implementation, with imports adjusted to pull Cache from @apollo/client/cache.
Deprecated aliases
src/core/deprecated.ts
Deprecated exported aliases MutationOptions and RefetchQueriesOptions updated to default/constraint TCache to Cache.Implementation.
API reports and extractor
.api-reports/*.api.md
Generated API reports updated to reflect the new Cache_2.Implementation/Cache.Implementation usage and API extractor warnings updated where needed.
Type test infrastructure
integration-tests/type-tests/cacheOverride/shared/index.ts, integration-tests/type-tests/*/tsconfig.json
Adds TestCache and a test() helper, and configures TypeScript project references for the integration type tests.
Cache override type validation
integration-tests/type-tests/cacheOverride/{classicSignature,modernSignature,defaults,invalid}/index.ts
Comprehensive type tests validating the override behavior across classic/modern signatures, default behavior, and invalid override rejection, covering client construction and React hooks.
Changelog
.changeset/fuzzy-hairs-tie.md
Documents the new TypeOverrides.cache augmentation example and describes how the declared cache type flows into client.cache and cache callback parameters.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

auto-cleanup

Suggested reviewers

  • phryneas
  • pragl

Poem

🐰 A TypeScript hop, a tiny tweak—

Cache now bends where you speak.
One override, types align,
Hooks and client dance in line. ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add overridable cache type' clearly and concisely summarizes the main change: introducing the ability to override the cache type via TypeOverrides, allowing users to specify concrete cache implementations at compile time.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@pkg-pr-new

pkg-pr-new Bot commented Jun 2, 2026

Copy link
Copy Markdown
npm i https://pkg.pr.new/apollographql/apollo-client/@apollo/client@13250

commit: 8df9c40


export type Implementation =
TypeOverrides extends { cache: infer TCache } ?
TCache extends ApolloCache ?

@jerelmiller jerelmiller Jun 2, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I chose to use ApolloCache as the type when the cache property is an invalid type (e.g. it isn't an ApolloCache subtype). Is this what we want? This "silently" fails in that the type is ignored completely and ApolloCache is used everywhere. Do we want this to be a bit more loud? If so, do we want to do like we did with default options and add a string message that points to our documentation?

Note: You can see the behavior in the cacheOverride/invalid/index.ts tests.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No strong opinions but my two cents: the silent fallback could make someone waste time wondering why client.cache is still ApolloCache?

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.api-reports/api-report-core.api.md (1)

219-263: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update the deprecated top-level cache aliases as well.

The generated surface still exports MutationOptions<TCache extends ApolloCache = ApolloCache> and RefetchQueriesOptions<TCache extends ApolloCache, TResult> later in this file (Lines 735 and 1227). That means consumers who still import those deprecated public names won't get the new override-aware cache typing even though ApolloClient.MutateOptions and ApolloClient.RefetchQueriesOptions now do.

Also applies to: 393-495

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.api-reports/api-report-core.api.md around lines 219 - 263, Update the
deprecated top-level cache alias exports so they use the new override-aware
cache implementation type instead of ApolloCache: replace the generic defaults
on MutationOptions and RefetchQueriesOptions (and any other top-level aliases in
the 393-495, 735, and 1227 ranges) so their TCache generic extends
Cache_2.Implementation (or the same override-aware type used by
ApolloClient.MutateOptions/ApolloClient.RefetchQueriesOptions) and mirror the
new signatures/constraints used by the ApolloClient.* variants to ensure
consumers importing the deprecated names get the same override-aware typing.
🧹 Nitpick comments (1)
integration-tests/type-tests/cacheOverride/invalid/index.ts (1)

31-49: ⚡ Quick win

Add a negative constructor check for the invalid override case.

This suite shows that exposed cache types fall back to ApolloCache, but it never asserts that TypeOverrides.cache = number does not leak into ApolloClient.Options. A regression allowing cache: 123 would still pass these tests.

Proposed addition
 test("ApolloClient constructor", () => {
+  {
+    const client = new ApolloClient({
+      // `@ts-expect-error` cache must still be an ApolloCache implementation
+      cache: 123,
+      link: ApolloLink.empty(),
+    });
+
+    expectTypeOf(client.cache).toEqualTypeOf<ApolloCache>();
+  }
+
   {
     const client = new ApolloClient({
       cache: new InMemoryCache(),
       link: ApolloLink.empty(),
     });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@integration-tests/type-tests/cacheOverride/invalid/index.ts` around lines 31
- 49, Add a negative TypeScript test to ensure TypeOverrides.cache does not leak
into ApolloClient.Options by attempting to construct new ApolloClient with an
invalid cache value and asserting a type error: in the "ApolloClient
constructor" test add a case that passes cache: 123 (or another non-cache
primitive) to ApolloClient constructor and mark it with a `@ts-expect-error` so
the compiler fails the test if the override leaked; reference ApolloClient,
ApolloClient.Options and TypeOverrides.cache when adding the check.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@integration-tests/type-tests/cacheOverride/classicSignature/index.ts`:
- Around line 1-8: The test file is instantiating new InMemoryCache() but
InMemoryCache is not imported; add InMemoryCache to the import list from
"`@apollo/client`" (the same import that currently brings in ApolloClient,
ApolloLink, Cache, TypedDocumentNode, MutationUpdaterFunction, ApolloCache) so
the symbol InMemoryCache is available for the instantiation in this file.

In `@integration-tests/type-tests/cacheOverride/modernSignature/index.ts`:
- Around line 1-8: The file uses InMemoryCache (seen in the expression cache:
new InMemoryCache()) but it isn't imported from `@apollo/client`; update the
import statement that currently lists ApolloClient, ApolloLink, Cache,
TypedDocumentNode, MutationUpdaterFunction, ApolloCache to also include
InMemoryCache so the type-test compiles and the usage of new InMemoryCache() is
resolved.

---

Outside diff comments:
In @.api-reports/api-report-core.api.md:
- Around line 219-263: Update the deprecated top-level cache alias exports so
they use the new override-aware cache implementation type instead of
ApolloCache: replace the generic defaults on MutationOptions and
RefetchQueriesOptions (and any other top-level aliases in the 393-495, 735, and
1227 ranges) so their TCache generic extends Cache_2.Implementation (or the same
override-aware type used by
ApolloClient.MutateOptions/ApolloClient.RefetchQueriesOptions) and mirror the
new signatures/constraints used by the ApolloClient.* variants to ensure
consumers importing the deprecated names get the same override-aware typing.

---

Nitpick comments:
In `@integration-tests/type-tests/cacheOverride/invalid/index.ts`:
- Around line 31-49: Add a negative TypeScript test to ensure
TypeOverrides.cache does not leak into ApolloClient.Options by attempting to
construct new ApolloClient with an invalid cache value and asserting a type
error: in the "ApolloClient constructor" test add a case that passes cache: 123
(or another non-cache primitive) to ApolloClient constructor and mark it with a
`@ts-expect-error` so the compiler fails the test if the override leaked;
reference ApolloClient, ApolloClient.Options and TypeOverrides.cache when adding
the check.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: ec587630-aecf-4ff3-afb0-641f46ea3a52

📥 Commits

Reviewing files that changed from the base of the PR and between a295b55 and 72fea26.

📒 Files selected for processing (19)
  • .api-reports/api-report-cache.api.md
  • .api-reports/api-report-core.api.md
  • .api-reports/api-report-react.api.md
  • .api-reports/api-report.api.md
  • .changeset/fuzzy-hairs-tie.md
  • integration-tests/type-tests/cacheOverride/classicSignature/index.ts
  • integration-tests/type-tests/cacheOverride/classicSignature/tsconfig.json
  • integration-tests/type-tests/cacheOverride/defaults/index.ts
  • integration-tests/type-tests/cacheOverride/defaults/tsconfig.json
  • integration-tests/type-tests/cacheOverride/invalid/index.ts
  • integration-tests/type-tests/cacheOverride/invalid/tsconfig.json
  • integration-tests/type-tests/cacheOverride/modernSignature/index.ts
  • integration-tests/type-tests/cacheOverride/modernSignature/tsconfig.json
  • integration-tests/type-tests/cacheOverride/shared/index.ts
  • integration-tests/type-tests/cacheOverride/shared/tsconfig.json
  • integration-tests/type-tests/tsconfig.json
  • src/cache/core/types/Cache.ts
  • src/core/ApolloClient.ts
  • src/react/hooks/useMutation.ts

Comment thread integration-tests/type-tests/cacheOverride/modernSignature/index.ts
@jerelmiller

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Comment thread src/core/ApolloClient.ts Outdated
Comment thread .changeset/fuzzy-hairs-tie.md
@github-actions github-actions Bot added the auto-cleanup 🤖 label Jun 5, 2026
@jerelmiller
jerelmiller merged commit bad7035 into release-4.3 Jun 9, 2026
46 of 47 checks passed
@jerelmiller
jerelmiller deleted the jerel/cache-type branch June 9, 2026 00:24
jerelmiller pushed a commit that referenced this pull request Jun 9, 2026
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to release-4.3, this
PR will be updated.

⚠️⚠️⚠️⚠️⚠️⚠️

`release-4.3` is currently in **pre mode** so this branch has
prereleases rather than normal releases. If you want to exit
prereleases, run `changeset pre exit` on `release-4.3`.

⚠️⚠️⚠️⚠️⚠️⚠️

# Releases
## @apollo/client@4.3.0-alpha.0

### Minor Changes

- [#13250](#13250)
[`bad7035`](bad7035)
Thanks [@jerelmiller](https://github.com/jerelmiller)! - Add the ability
to define the cache type for the client. `client.cache` currently
returns `ApolloCache` as the cache type regardless of what cache you've
provided to `ApolloClient`.

Declare the cache type using the `cache` property in the `TypeOverrides`
interface to set the cache implementation used for the client.

    ```ts
    // apollo.d.ts
    import type { InMemoryCache } from "@apollo/client";

    declare module "@apollo/client" {
      export interface TypeOverrides {
        cache: InMemoryCache;
      }
    }
    ```

Now anywhere `cache` is accessible, the type is the declared cache type:

    ```ts
    client.cache;
    //     ^? InMemoryCache

    client.mutate({
      update: (cache) => {
        //     ^? InMemoryCache
      },
    });
    ```

    > [!NOTE]
> Setting a cache type enforces that cache type in the `cache` option
for the `ApolloClient` constructor.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
DaleSeo added a commit that referenced this pull request Jun 10, 2026
As a quick follow-up to PR #13250, this fixes some cache override typing
paths that still allowed `ApolloCache`, while the public mutation and
refetch APIs now expect `Cache.Implementation`. Keeping these
constraints aligned ensures that user-declared cache overrides work
consistently through `QueryInfo`, internal refetch options, and
deprecated React mutation aliases. We also regenerated the API reports
so that the published type surface shows the corrected constraints.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Aligned cache-related type constraints across the library for
consistency. TypeScript users working with custom cache implementations
may notice updated type signatures in mutation helpers and query-related
APIs.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
@coderabbitai coderabbitai Bot mentioned this pull request Jun 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants